package galaxy.app.network.http.server;

import galaxy.app.Galaxy;
import galaxy.app.log.LogHelper;
import galaxy.kernel.exception.ServerBootstrapException;
import galaxy.kernel.system.AbstractECSSystem;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.stream.ChunkedWriteHandler;

public class HttpServerSystem extends AbstractECSSystem {
    HttpServerComponent c;

    public HttpServerSystem(){
        c = Galaxy.components().getSingle(HttpServerComponent.class);
        c.handler = new HttpServerHandler();
    }

    @Override
    public void start(){
        if (c == null) {
            return ;
        }
        if (c.port <= 0) {
            LogHelper.debug("http server not started.");
            return;
        }

        LogHelper.info("http server start on {}", c.port);
        ServerBootstrap bootstrap = new ServerBootstrap();
        // Socket参数，服务端接受连接的队列长度，如果队列已满，客户端连接将被拒绝。默认值，Windows为200，其他为128。
        bootstrap.option(ChannelOption.SO_BACKLOG, 1024);
        bootstrap.option(ChannelOption.SO_REUSEADDR, true);

        bootstrap.group(c.bossGroup, c.workerGroup).channel(NioServerSocketChannel.class);
        bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            public void initChannel(SocketChannel ch) {
                ChannelPipeline p = ch.pipeline();
                p.addLast(new HttpServerCodec());
                p.addLast(new HttpObjectAggregator(c.maxContentLength));
                p.addLast(new ChunkedWriteHandler());
                p.addLast(c.handler);
            }
        });

        try {
            bootstrap.bind(c.port).sync();
            LogHelper.info("http server start is success.");
        } catch (Exception e) {
            throw new ServerBootstrapException("目标端口已被占用 port=" + c.port, e);
        }
    } 
}
